﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Common.Utilities;
using Common.Utilities.TextMatch;

namespace Workflows.Components.TextMining.Collapse
{
    /// <summary>
    /// 
    /// </summary>
    public class PersonNameComparer:IAttributeComparer
    {
        #region const 
        //private const int InitialMatchScore = 15;
        private const int MinLenWhenSubstringMatch = 3;
        //private const int MinPercentOfLetterMatchWithinSubString = 75;
        //private const double SubStringMatchWeight = 0.80;
        //private const double SoundexWeight = 0.45;
        //private const double MetaphoneWeight = 0.15;
        #endregion

        private SqlDbType _FieldDbType;

        #region IAttributeComparer Members
        /// <summary>
        /// specify either use code snippet or class
        /// </summary>
        public AttributeComparerType ComparerType
        {
            get
            {
                return AttributeComparerType.ClassComparer;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public SqlDbType FieldDbType
        {
            get { return _FieldDbType; }
            set { _FieldDbType = value;}
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <param name="penalty"></param>
        /// <param name="conn"></param>
        /// <param name="unevenDistTableName"></param>
        /// <returns></returns>
        public double Compare(object value1, object value2, double penalty, SqlConnection conn, string unevenDistTableName)
        {
            if (value1 == null || value2 == null || value1 == DBNull.Value || value2 == DBNull.Value || 
                value1.ToString().Length == 0 || value2.ToString().Length == 0)
                return 0.0;

            string val1 = value1.ToString();
            string val2 = value2.ToString();
            try
            {
                if (val1.ToLower() == val2.ToLower())
                    return 1.00;
                else if (val1.Length == 1 || val2.Length == 1)
                {
                    if (val1.Substring(0, 1).ToLower() == val2.Substring(0, 1).ToLower())
                    {
                        return 0.75;
                    }
                }
                else if (StringUtil.LongestCommonSubsequence(val1, val2) >= MinLenWhenSubstringMatch)
                {
                    int commonStrLen = StringUtil.LongestCommonSubsequence(val1, val2);
                    return (double)commonStrLen / Math.Max(val1.Length, val2.Length);
                }
                else if (this.GetSoundexEncoding(val1) == this.GetSoundexEncoding(val2))
                    return 0.50;
                else if (this.GetMetaphoneEncoding(val1) == this.GetMetaphoneEncoding(val2))
                    return 0.35;

                return penalty;
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
                return 0.0;
            }
        }

        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="conn"></param>
        /// <param name="unevenDistTableName"></param>
        /// <returns></returns>
        public object Merge(List<object> values, SqlConnection conn, string unevenDistTableName)
        {
            if(values==null || values.Count==0)
                return null;
            Dictionary<string,int> valueByCount=new Dictionary<string, int>();
            foreach(object obj in values)
            {
                string val = obj.ToString().ToUpper();
                if(!string.IsNullOrEmpty(val))
                {
                    if(valueByCount.ContainsKey(val))
                    {
                        valueByCount[val] = valueByCount[val] + 1;
                    }
                    else
                    {
                        valueByCount.Add(val,1);
                    }
                }
            }
            if(valueByCount.Count==0)
                return null;
            else if(valueByCount.Count==1)
            {
                string[] vals=new string[valueByCount.Count];
                valueByCount.Keys.CopyTo(vals,0);
                return vals[0];
            }
            else
            {
                string[] vals = new string[valueByCount.Count];
                valueByCount.Keys.CopyTo(vals, 0);
                string topValByCount = vals[0];
                string secondTopValByCount = vals[1];
                string tmp;
                if (valueByCount[topValByCount] < valueByCount[secondTopValByCount])
                {
                    tmp = topValByCount;
                    topValByCount = secondTopValByCount;
                    secondTopValByCount = tmp;
                }
                for (int i = 2; i < vals.Length; i++)
                {
                    tmp = vals[i];
                    if(valueByCount[tmp]>valueByCount[secondTopValByCount])
                    {
                        if(valueByCount[tmp]>valueByCount[topValByCount])
                        {
                            secondTopValByCount = topValByCount;
                            topValByCount = tmp;
                        }
                    }
                    else
                    {
                        secondTopValByCount = tmp;
                    }
                }
                if(valueByCount[topValByCount]==valueByCount[secondTopValByCount])
                {
                    if (topValByCount.Length >= secondTopValByCount.Length)
                        return topValByCount;
                    else
                    {
                        if (this.GetFrequencyForValue(conn, unevenDistTableName, topValByCount) > 
                            this.GetFrequencyForValue(conn, unevenDistTableName, secondTopValByCount))
                        {
                            return topValByCount;
                        }
                        else
                            return secondTopValByCount;
                    }
                }
                else
                {
                    return topValByCount;
                }
            }
        }

        #endregion

        #region dist frequency
        private int GetFrequencyForValue(SqlConnection conn, string distTableName, string fieldValue)
        {
            return 0;
        }
        #endregion

        #region phonetic
        /// <summary>
        /// soundex encoding of string
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public string GetSoundexEncoding(string value)
        {
            SoundexConverter converter=new SoundexConverter();
            return converter.Convert(value);
        }

        /// <summary>
        /// metaphone encoding
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public string GetMetaphoneEncoding(string value)
        {
            MetaphoneConverter converter = new MetaphoneConverter();
            return converter.Convert(value);
        }
        #endregion
    }
}
